﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;

namespace BizElements.Generator
{
    public partial class SpListCtl : UserControl
    {
        #region Fields.

        IMetadataSource metaSource;
        Dictionary<string, object> selectedProcsInProjectSettings = new Dictionary<string, object>();

        #endregion

        public SpListCtl()
        {
            InitializeComponent();
        }        

        #region Properties, getters, setters.

        [Browsable(false)]
        public IMetadataSource MetaDataSource
        {
            get { return this.metaSource; }
            set { SetMetaSource(value); }
        }

        private void SetMetaSource(IMetadataSource value)
        {
            if (value == null)
            {
                this.uiProcedures.Items.Clear();
                this.metaSource = null;
            }
            else
            {
                bool hasChanged = (this.metaSource == null) || (this.metaSource.ConnectionString != value.ConnectionString);
                this.metaSource = value;
                if (hasChanged)
                    RefreshProcedureList();
            }
        }

        [Browsable(false)]
        public string[] SelectedProcedures
        {
            get { return GetSelectedProcedures(); }
        }

        private string[] GetSelectedProcedures()
        {
            List<string> selectedProcs = new List<string>();
            foreach (ListViewItem table in this.uiProcedures.Items)
            {
                if (table.Checked)
                    selectedProcs.Add(table.Text);
            }

            selectedProcs.Sort();
            return selectedProcs.ToArray();
        }

        #endregion

        #region Refresh.

        private void uiRefresh_Click(object sender, EventArgs e)
        {
            string[] procNames = this.SelectedProcedures;
            this.selectedProcsInProjectSettings = ToDictionary(procNames);
            RefreshProcedureList();
        }

        private void RefreshProcedureList()
        {
            if (this.MetaDataSource == null)
                return;

            this.Enabled = false;
            string prefixFilter = this.uiExcludedPrefixes.Text.Trim();
            string[] excludedPrefixes = ParseExcludedPrefixes(prefixFilter);
            var procedures = this.MetaDataSource.FetchStoredProcedures(excludedPrefixes);

            this.uiProcedures.BeginUpdate();
            this.uiProcedures.Items.Clear();
            foreach (SqlObjectHeader sp in procedures)
            {
                ListViewItem item = this.uiProcedures.Items.Add(sp.Name);
                item.SubItems.Add(sp.TypeName);
                item.Tag = sp.Type;
                item.Checked = this.selectedProcsInProjectSettings.ContainsKey(sp.Name);
            }

            this.uiProcedures.EndUpdate();
            this.Enabled = true;
        }

        private static string[] ParseExcludedPrefixes(string prefixFilter)
        {
            string[] filterParts = prefixFilter.Split(';');
            List<string> prefixes = new List<string>();
            foreach (string part in filterParts)
            {
                string trimmed = part.Trim();
                if (trimmed.Length > 0)
                    prefixes.Add(trimmed);
            }

            return prefixes.ToArray();
        }

        #endregion

        #region Settings.

        public void ReadSettings(BizElementsSettings settings)
        {
            this.uiExcludedPrefixes.Text = settings["SpList_ExcludedPrefixes"];
            string delimitedProcs = settings["SpList_SelectedProcedures"] ?? "";
            string[] procNames = delimitedProcs.Split(';');
            Array.Sort<string>(procNames);
            this.selectedProcsInProjectSettings = ToDictionary(procNames);
            RefreshProcedureList();
        }

        public void WriteSettings(BizElementsSettings settings)
        {
            settings["SpList_ExcludedPrefixes"] = this.uiExcludedPrefixes.Text.Trim();
            string[] procNames = this.SelectedProcedures;
            Array.Sort<string>(procNames);
            settings["SpList_SelectedProcedures"] = string.Join(";", procNames);
            this.selectedProcsInProjectSettings = ToDictionary(procNames);
        }

        private static Dictionary<string, object> ToDictionary(IEnumerable<string> procNames)
        {
            Dictionary<string, object> indexedList = new Dictionary<string, object>();
            foreach (string sp in procNames)
                indexedList[sp] = null;

            return indexedList;
        }

        #endregion
    }
}
